//-----------------------------------------------------------------------
//
// Cyclone (Sumo) Service
//
// Updated for RDS 2008 (V2.0)
//
//  $File: CycloneTypes.cs $ $Revision: 1 $
//-----------------------------------------------------------------------

using Microsoft.Ccr.Core;
using Microsoft.Dss.Core.Attributes;
using Microsoft.Dss.ServiceModel.Dssp;
using System;
using System.Collections.Generic;
using W3C.Soap;
using sumoplayer = Microsoft.Robotics.Services.Cyclone;
using System.ComponentModel;
using webcam = Microsoft.Robotics.Services.WebCam.Proxy;

namespace Microsoft.Robotics.Services.Cyclone
{
    #region Operation Port
    /// <summary>
    /// Cyclone Main Operations Port
    /// </summary>
    [ServicePort]
    public class CycloneOperations : PortSet
    {
        public CycloneOperations()
            : base(
                typeof(DsspDefaultLookup),
                typeof(DsspDefaultDrop),
                typeof(Get)
            )
        {
        }

        public static implicit operator Port<Get>(CycloneOperations portSet)
        {
            if (portSet == null)
            {
                return null;
            }
            return (Port<Get>)portSet[typeof(Get)];
        }

        public void Post(Get msg)
        {
            base.PostUnknownType(msg);
        }

        public PortSet<CycloneState, Fault> Get()
        {
            Get get = new Get();
            this.Post(get);
            return get.ResponsePort;
        }
    }

    #endregion

    #region Data Contracts

    #region Enums

    /// <summary>
    /// The current mode of the sumo player
    /// The lower the number, the more precedence the mode has.
    /// </summary>
    [DataContract]
    public enum SumoMode
    {
        /// <summary>
        /// Uninitialized
        /// </summary>
        Uninitialized = 0x00,

        /// <summary>
        /// Initializing the sumoplayer
        /// </summary>
        Initializing = 0x01,

        /// <summary>
        /// Sumo is initialized and Ready to start
        /// </summary>
        Ready = 0x02,

        /// <summary>
        /// Count down to start moving
        /// </summary>
        Pending = 0x03,

        /// <summary>
        /// Opponent is in direct proximity
        /// </summary>
        Contact = 0x04,
        
        /// <summary>
        /// We are over the line
        /// </summary>
        AvoidBoundary = 0x05,

        /// <summary>
        /// The opponent is in view
        /// </summary>
        Tracking = 0x06,

        /// <summary>
        /// Wander around
        /// </summary>
        Wander = 0x07,

        /// <summary>
        /// Follow the edge
        /// </summary>
        FollowLine = 0x08,

        /// <summary>
        /// Sensors are old
        /// </summary>
        Blind = 0x09,
    }

    [DataContract]
    [Flags]
    public enum Direction
    {
        Stopped = 0,

        Left = 0x01,
        Right = 0x02,
        Reverse = 0x04,
        Spinning = 0x08,
        Straight = 0x10,

        ReverseLeft = 0x05,
        ReverseRight = 0x06,

        SpinLeft = 0x09,
        SpinRight = 0x0A,
    }
    #endregion

    #region State
    /// <summary>
    /// The Cyclone State
    /// </summary>
    [DataContract()]
    public class CycloneState
    {
        #region Configuration

        /// <summary>
        /// The Low threshhold for a line on the ground
        /// </summary>
        [DataMember]
        public int LineThreshHoldLow;

        /// <summary>
        /// The High threshhold for a line on the ground
        /// </summary>
        [DataMember]
        public int LineThreshHoldHigh;

        /// <summary>
        /// The polling frequency for Sumo
        /// processing loop.
        /// </summary>
        [DataMember]
        public double PollingFrequency = 200.0;

        /// <summary>
        /// The name of this Sumo player
        /// </summary>
        [DataMember]
        public string Name;

        #endregion

        #region Runtime State

        /// <summary>
        /// The current mode of the Sumo player
        /// </summary>
        [DataMember]
        [Browsable(false)]
        public SumoMode SumoMode;

        /// <summary>
        /// Status
        /// </summary>
        [DataMember]
        [Browsable(false)]
        public Direction Direction;

        /// <summary>
        /// Continue in the current mode until
        /// NextModeCheck (or higher priority event)
        /// </summary>
        [DataMember]
        [Browsable(false)]
        public DateTime NextModeCheck;

        /// <summary>
        /// Time last iRobot Sensors acquired
        /// </summary>
        [DataMember]
        [Browsable(false)]
        public DateTime LastIRobotSensors = DateTime.MinValue;

        /// <summary>
        /// Time last image acquired
        /// </summary>
        [DataMember]
        [Browsable(false)]
        public DateTime LastImage = DateTime.MinValue;

        /// <summary>
        /// The last result from the camera
        /// </summary>
        [DataMember]
        [Browsable(false)]
        public ImageProcessResult ImageResult;

        /// <summary>
        /// Sumo player sensors
        /// </summary>
        [DataMember]
        [Browsable(false)]
        public Sensors Sensors;


        /// <summary>
        /// Left wheel mm/sec
        /// </summary>
        [DataMember]
        [Browsable(false)]
        public int LeftSpeed;

        /// <summary>
        /// Right wheel mm/sec
        /// </summary>
        [DataMember]
        [Browsable(false)]
        public int RightSpeed;

        #endregion
    }
    #endregion

    #region Sensors
    /// <summary>
    /// Sumo Sensors
    /// </summary>
    [DataContract]
    [DataMemberConstructor]
    public class Sensors
    {
        /// <summary>
        /// Left Wheel is stalled
        /// </summary>
        [DataMember]
        public bool LeftWheelStalled;

        /// <summary>
        /// Right Wheel is stalled
        /// </summary>
        [DataMember]
        public bool RightWheelStalled;

        /// <summary>
        /// Left Bumper is depressed
        /// </summary>
        [DataMember]
        public bool LeftBumper;

        /// <summary>
        /// Right Bumper is depressed
        /// </summary>
        [DataMember]
        public bool RightBumper;

        /// <summary>
        /// One or more of the iRobot wheels have dropped
        /// </summary>
        [DataMember]
        public bool DroppedWheels;

        /// <summary>
        /// Front of the iRobot is raised
        /// </summary>
        [DataMember]
        public bool DroppedCaster;

        /// <summary>
        /// Left wheel of the iRobot is raised
        /// </summary>
        [DataMember]
        public bool DroppedLeftWheel;

        /// <summary>
        /// Right wheel of the iRobot is raised
        /// </summary>
        [DataMember]
        public bool DroppedRightWheel;

        #region Lines on the Floor
        /// <summary>
        /// Are we over the line?
        /// </summary>
        [DataMember]
        public bool LineDetected;

        /// <summary>
        /// Line detected on the Left
        /// </summary>
        [DataMember]
        public bool LineLeft;

        /// <summary>
        /// Line detected on the Front Left
        /// </summary>
        [DataMember]
        public bool LineFrontLeft;

        /// <summary>
        /// Line detected on the Right
        /// </summary>
        [DataMember]
        public bool LineRight;

        #endregion

        /// <summary>
        /// Line detected on the Front Right
        /// </summary>
        [DataMember]
        public bool LineFrontRight;

        /// <summary>
        /// Sensors
        /// </summary>
        public Sensors()
        {
        }

        /// <summary>
        /// Sensors
        /// </summary>
        public Sensors(bool leftWheelStalled, bool rightWheelStalled, bool leftBumper, bool rightBumper)
        {
            this.LeftWheelStalled = leftWheelStalled;
            this.RightWheelStalled = rightWheelStalled;
            this.LeftBumper = leftBumper;
            this.RightBumper = rightBumper;
        }
    }
    #endregion

    #region Drive
    /// <summary>
    /// Drive the iRobot
    /// </summary>
    [DataContract]
    public class Drive
    {
        /// <summary>
        /// Count down for movement.
        /// </summary>
        [DataMember]
        public double MilliSeconds = 0.0;

        /// <summary>
        /// Left wheel mm/sec
        /// </summary>
        [DataMember]
        public int LeftSpeed;

        /// <summary>
        /// Right wheel mm/sec
        /// </summary>
        [DataMember]
        public int RightSpeed;

    }

    /// <summary>
    /// Decrement
    /// </summary>
    [DataContract]
    public class Decrement { }


    /// <summary>
    /// Decrement
    /// </summary>
    [DataContract]
    public class SetMode
    {
        [DataMember]
        public SumoMode Mode;
    }
    #endregion

    #region Custom Image Processing
    /// <summary>
    /// ImageProcessResult
    /// </summary>
    [DataContract]
    public class ImageProcessResult
    {
        /// <summary>
        /// X Mean
        /// </summary>
        [DataMember]
        public int XMean;

        /// <summary>
        /// Y Mean
        /// </summary>
        [DataMember]
        public int YMean;

        /// <summary>
        /// Area
        /// </summary>
        [DataMember]
        public int Area;

        /// <summary>
        /// TimeStamp
        /// </summary>
        [DataMember]
        public DateTime TimeStamp;
#if false
        public double XStdDev;
        public double YStdDev;
        public double XSkew;
        public double YSkew;
#endif
    }

    #endregion

    #endregion

    #region Operation Types

    /// <summary>
    /// Cyclone Get Operation
    /// </summary>
    public class Get : Get<GetRequestType, PortSet<CycloneState, Fault>>
    {
    }

    #endregion

    #region Contract
    /// <summary>
    /// Cyclone Contract class
    /// </summary>
    public sealed class Contract
    {
        /// <summary>
        /// The Dss Service contract
        /// </summary>
        public const String Identifier = "http://www.promrds.com/contracts/2007/11/cyclone.html";
    }
    #endregion

}
